#!/usr/bin/python
"""
 Title: provider.py
 Author: Matthew Tanner
 Project: Facultimes
 This is an Oregon State University project built as a requirement for CS419. 
 The project is a collaboration between Matthew Tanner, Arnold Baghomian, and
 Joseph Helgeson. 
 """

import cgi
import sys
import json
import cgitb
import logging

from Scheduler import Scheduler
from datetime import datetime	

class Provider:
	"""Passes data to and from the web interface.

	Retrieves requests and sends responses back to the web interface 
	facultimes.html. Request should be by post with standard form parameters.
	Required paramaters are a number of names, and time window with parameter
	examples as follows:

	user1 = "schmo, joe"
	user2 = "smith, john"
	user3 = "twostep, terry"
	... user(n) = "parker, peggy"

	startwindow = "08/15/14 05:00"
	endwindow = "08/17/14 20:00"

	If a solution is obtained, its sent back in the respnse along with the
	original parameters. Otherwise, and error message is sent. Both are encoded
	as JSON. Examples are here:

 	solution = {"userlist": [{"name": "blow, joe"},
 					{"name": "smith, john"},
 					{"name": "bob, billy"},
					{"name": "parker, peggy"}],
		"window": {"start": "0700 081514", "end": "1700 081514"},
		"attendees":[{"name": "bob, billy"},
					{"name": "parker, peggy"}],
		"times":[{"start": "0700 081514", "end": "0730 081514"},
				{"start": "1430 081514", "end": "1515 081514"}]}

	error = {"error": 'error message'}		

    Attributes: 
    	TIME_FORMAT: Constant string for use in datetime conversion.
    """	
	TIME_FORMAT = "%m/%d/%Y %H:%M"

	# Initialize member variables
	def __init__(self, reqData):
		self.form = reqData
		self.data = {}
		self.solution = {}
		self.error = {}

	# Parse request and assign parameters
	def parseRequest(self):
		self.userlist = []
		try:
			for key in self.form.keys():
				if key[:4] == "name":
					self.userlist.append(self.form.getvalue(key))

			string = self.form.getvalue("startwindow")
			self.startWindow = datetime.strptime(string, Provider.TIME_FORMAT)
			string = self.form.getvalue("endwindow")
			self.endWindow = datetime.strptime(string, Provider.TIME_FORMAT)
		except ValueError as err:
			self.error["error"] = "Error: Time/Date values must be in form MM/DD/YYYY HH:MM"
			logging.exception("parseRequest() Error: Time/Date values must be in form MM/DD/YYYY HH:MM")
			return -1		
		except Exception as err:
			self.error["error"] = "Error: Time/Date values must be in form MM/DD/YYYY HH:MM"
			logging.exception("parseRequest() Error: %s" % self.error)
			return -1

	# Send solution or error back in response
	def sendResponse(self, response):	
		print("Content-Type: text/plain\n\n")
		print json.dumps(response)

	# Get solution by passing parameters to back-end API
	def getSolution(self):
		s = Scheduler()
		s.users = self.userlist
		s.startWindow = self.startWindow
		s.endWindow = self.endWindow
		if(s.schedule() == -1):
			self.error['error'] = s.error
			return -1
		return s.solution	

	# get valid user list for form input validation
	def getValidUsers(self):
		validUserDict = {}
		s = Scheduler()
		validUserList = s.validUsers
		if validUserList == -1:
			self.error['error'] = s.error
			return -1
		validUserDict['validusers'] = validUserList
		return validUserDict


# Post from web interface starts main
def main():
	logging.basicConfig(filename='provider.log', level=logging.DEBUG, 
                    format='%(asctime)s %(levelname)s %(name)s %(message)s')
	logger=logging.getLogger(__name__)

	try:


		form = cgi.FieldStorage()
		p = Provider(form)	

		if 'validusers' in form.keys():
			validUsers = p.getValidUsers();
			if validUsers == -1:
				p.sendResponse(p.error)
				sys.exit(1)
			else:
				p.sendResponse(validUsers)
				sys.exit(0)

		if(p.parseRequest() == -1):
			p.sendResponse(p.error)
			sys.exit(1)

		solution = p.getSolution()
		if solution == -1:
			p.sendResponse(p.error)
			sys.exit(1)

		p.sendResponse(solution)
	except Exception as err:
		print("Content-Type: text/plain\n\n")
		response = {"error": str(err)}
		print json.dumps(response)
		logging.exception("Main Error")


if __name__ == "__main__":
    main()
